import gtk
#import connectivity.client
import parser.parser
import parser.classparser
import display.disp
#import display.test
import obj_types.obj_text
import connectivity.server
import colors

gtk.gdk.threads_init()

class StartUpDisp(gtk.EventBox):
	parent = None
	
	def __init__(self, parent):
		gtk.EventBox.__init__(self)
		self.parent = parent
		
		self.set_border_width(10)
		self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.black))
		
		box = gtk.Table(4, 3, False)
		box.set_border_width(10)
		box.set_col_spacings(3)
		box.set_row_spacings(3)
		self.add(box)
		box.show()
		
#		box_fields = gtk.HBox(False, 0)
#		box.pack_start(box_fields, False, False, 0)
#		box_fields.show()
#		
#		box_labels = gtk.VBox(True, 3)
#		box_fields.pack_start(box_labels, False, False, 0)
#		box_labels.show()
		
		l_pres = gtk.Label("Presentation:")
		l_pres.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.yellow))
		l_pres.set_alignment(0.0, 0.5)
		l_pres.show()
		box.attach(l_pres, 0, 1, 0, 1)
		
		l_class = gtk.Label("Class:  ")
		l_class.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.yellow))
		l_class.set_alignment(0.0, 0.5)
		l_class.show()
		box.attach(l_class, 0, 1, 1, 2)

		l_pass = gtk.Label("Password: ")
		l_pass.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.yellow))
		l_pass.set_alignment(0.0, 0.5)
		l_pass.show()
		box.attach(l_pass, 0, 1, 2, 3)

#		box_entries = gtk.VBox(True, 3)
#		box_fields.pack_start(box_entries, False, False, 0)
#		box_entries.show()
#		
		self.e_pres = gtk.Entry()
		self.e_pres.show()
		box.attach(self.e_pres, 1, 2, 0, 1)
		
		self.e_class = gtk.Entry()
		self.e_class.show()
		box.attach(self.e_class, 1, 2, 1, 2)

		self.e_pass = gtk.Entry()
		self.e_pass.show()
		box.attach(self.e_pass, 1, 2, 2, 3)
		
		btn_pres = display.disp.ColoredButton("...", 30, 20)
		btn_pres.connect("clicked", self.btn_pres_clicked)
		btn_pres.show()
		box.attach(btn_pres, 2, 3, 0, 1)
		
		btn_class = display.disp.ColoredButton("...", 30, 20)
		btn_class.connect("clicked", self.btn_class_clicked)
		btn_class.show()
		box.attach(btn_class, 2, 3, 1, 2)
	
		box_buttons = gtk.HBox(False, 3)
		box_buttons.show()
		box.attach(box_buttons, 1, 2, 3, 4)
		
		btn_ok = display.disp.ColoredButton("OK")
		box_buttons.pack_end(btn_ok, False, False, 0)
		btn_ok.connect("clicked", self.btn_ok_clicked)
		btn_ok.show()
		
		btn_cancel = display.disp.ColoredButton("Cancel")
		box_buttons.pack_end(btn_cancel, False, False, 0)
		btn_cancel.connect("clicked", lambda wid: gtk.main_quit())
		btn_cancel.show()
#		
#		btn_file = gtk.Button(" ", gtk.STOCK_OPEN)
#		box_buttons.pack_end(btn_file, False, False, 0)
#		btn_file.show()
		
	def btn_ok_clicked(self, widget):
		presentation = self.e_pres.get_text()
		password = self.e_pass.get_text()
		address = self.e_class.get_text()
		
		self.parent.classparser = parser.classparser.classparser(address, True)
		if self.parent.classparser.is_ok:		
			self.parent.server = connectivity.server.Server(presentation, password, True)
			self.parent.server.connect('',50000)
			if self.parent.server.bool_ok:
				self.parent.parser = parser.parser.Presentation(presentation, True, self.parent.server)
				if self.parent.parser.is_ok:
					self.parent.display_slide(0)
				else:
					self.parent.server.stop()
					self.parent.display_error ("Invalid presentation file. Please review.")
			else:
				self.parent.display_error ("Server could not be started.")
		else:
			self.parent.display_error ("Class roster could not be loaded. Check class file.")							
		
	def btn_pres_clicked(self, widget):
		buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)
		dialog = gtk.FileChooserDialog("Select presentation file...", None, gtk.FILE_CHOOSER_ACTION_OPEN, buttons)
		dialog.set_default_response(gtk.RESPONSE_OK)
		response = dialog.run()
		if response == gtk.RESPONSE_OK:
			self.e_pres.set_text(dialog.get_filename())
		dialog.destroy()
		
	def btn_class_clicked(self, widget):
		buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)
		dialog = gtk.FileChooserDialog("Select class file...", None, gtk.FILE_CHOOSER_ACTION_OPEN, buttons)
		dialog.set_default_response(gtk.RESPONSE_OK)
		response = dialog.run()
		if response == gtk.RESPONSE_OK:
			self.e_class.set_text(dialog.get_filename())
		dialog.destroy()
		
class SrvDisp(gtk.EventBox):
	parent = None
	crt_slide = 0
	
	def __init__(self, parent):
		gtk.EventBox.__init__(self)
		self.parent = parent
		
		self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.darkgreen))
		self.show()
		
		self.content = gtk.VBox(False, 30)
		self.add(self.content)
		self.content.set_border_width(0)
		self.content.show()
		
		self.align = gtk.Alignment(0.5, 0.5, 1.0, 1.0)
		self.align.show()
		self.content.pack_start(self.align, True, True, 0)
		
		self.pres = display.disp.Disp([colors.black, [obj_types.obj_text.Text("")]])
		self.pres.show()
		self.align.add(self.pres)
		
		box_buttons = gtk.HBox(False, 10)
		self.content.pack_start(box_buttons, False, False, 0)
		box_buttons.show()
		
		btn_close = display.disp.ColoredButton("Close")
		box_buttons.pack_end(btn_close, False, False, 0)
		btn_close.connect("clicked", lambda wid : parent.display_close())
		btn_close.show()
		
		self.btn_next = display.disp.ColoredButton("Next")
		box_buttons.pack_end(self.btn_next, False, False, 0)
		self.btn_next.connect("clicked", self.btn_next_clicked)
		self.btn_next.show()
		
		self.btn_prev = display.disp.ColoredButton("Prev")
		box_buttons.pack_end(self.btn_prev, False, False, 0)
		self.btn_prev.connect("clicked", self.btn_prev_clicked)
		self.btn_prev.show()
		
		btn_list = display.disp.ColoredButton("List")
		box_buttons.pack_start(btn_list, False, False, 0)
		btn_list.connect("clicked", lambda wid : parent.display_list())
		btn_list.show()
		
	def display_slide(self, nr):
		page = self.parent.parser.get_slide(nr)
		
		if self.align.get_child() is not None:
			self.align.remove(self.align.get_child())
		
		self.pres.destroy()
		self.pres = display.disp.Disp(page)
		self.pres.show()
		self.align.add(self.pres)
		
		self.btn_next.set_sensitive(self.crt_slide + 1 < self.parent.parser.get_number_of_slides())
		self.btn_prev.set_sensitive(self.crt_slide > 0)
		
	def btn_next_clicked(self, widget):
		self.crt_slide = self.crt_slide + 1
		self.parent.parser.get_slide(self.crt_slide)
		self.display_slide(self.crt_slide)
		self.parent.server.set_current_slide(self.crt_slide)
		
	def btn_prev_clicked(self, widget):
		self.crt_slide = self.crt_slide - 1
		self.parent.parser.get_slide(self.crt_slide)
		self.display_slide(self.crt_slide)
		self.parent.server.set_current_slide(self.crt_slide)

class ListDisp(gtk.EventBox):
	parent = None
	
	def __init__(self, parent, list):
		gtk.EventBox.__init__(self)
		self.parent = parent

		self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.black))
		
		box = gtk.VBox(False, 10)
		box.set_border_width(10)
		box.show()
		self.add(box)

		l_student = gtk.Label("Students:")
		l_student.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.student_grey))
		# TODO: make background colors.student_bg_selected -- it needs an eventbox
		l_student.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.student_bg_selected))
		# TODO: make background colors.student_bg_selected -- it needs an eventbox
		l_student.show()
		box.pack_start(l_student, False, False, 0)

		l_student = gtk.Label("\n")
		l_student.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.student_grey))
		l_student.show()
		box.pack_start(l_student, False, False, 0)

		list_connected = list[:]
		list_notconnected = self.parent.classparser.get_students()[:]
		list_notinvited = [] 
		
		for student in list_connected[:]:
			if student in list_notconnected:
				# student in in class and connected. Super - duper
				list_notconnected.remove(student)
			else:
				# student is connected but not in class - :|
				list_notinvited.append(student)
				list_connected.remove(student)
		
		# now we selected the students:
		# list_connected = in class and connected
		# list_notconnected = in class and not yet connected
		# list_notinvited = fly that has found the milk pot (Ro: musca in lapte) 

		list_connected.sort()		# cannot kick these guys
		list_notconnected.sort()	# cannot kick these guys
		list_notinvited.sort()		# SHOULD KICK these guys
		
		for student in list_connected:
			l_student = gtk.Label(student)
			l_student.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.student_green))
			l_student.show()
			box.pack_start(l_student, False, False, 0)
		
		for student in list_notconnected:
			l_student = gtk.Label(student)
			l_student.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.student_grey))
			l_student.show()
			box.pack_start(l_student, False, False, 0)

		for student in list_notinvited:
			l_student = gtk.Label(student)
			l_student.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.student_red))
			# add KICK button here
			l_student.show()
			box.pack_start(l_student, False, False, 0)
		
		l_student = gtk.Label("\n")
		l_student.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.student_grey))
		l_student.show()
		box.pack_start(l_student, False, False, 0)

		if len(list_notconnected) or len(list_connected) or len(list_notinvited): 
			l_student = gtk.Label("Legend:")
			l_student.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.student_grey))
			# TODO: make background colors.student_bg_selected -- it needs an eventbox
			l_student.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.student_bg_selected))
			# TODO: make background colors.student_bg_selected -- it needs an eventbox
			l_student.show()
			box.pack_start(l_student, False, False, 0)
			
			if len(list_connected):
				l_student = gtk.Label("In class and connected")
				l_student.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.student_green))
				l_student.show()
				box.pack_start(l_student, False, False, 0)
			
			if len(list_notconnected):
				l_student = gtk.Label("In class but not connected")
				l_student.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.student_grey))
				l_student.show()
				box.pack_start(l_student, False, False, 0)
		
			if len(list_notinvited):
				l_student = gtk.Label("Not in class but connected")
				l_student.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.student_red))
				l_student.show()
				box.pack_start(l_student, False, False, 0)
		
		box_buttons = gtk.HBox(False, 3)
		box_buttons.show()
		box.pack_end(box_buttons, False, False, 0)
		
		btn_ok = display.disp.ColoredButton("OK")
		box_buttons.pack_end(btn_ok, True, False, 0)
		btn_ok.connect("clicked", lambda wid: self.parent.display_slide(self.parent.presentation.crt_slide))
		btn_ok.show()

class CloseDisp(gtk.EventBox):
	parent = None
	
	def __init__(self, parent):
		gtk.EventBox.__init__(self)
		self.parent = parent

		self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.black))
		
		box = gtk.VBox(False, 10)
		box.set_border_width(10)
		box.show()
		self.add(box)

		l_message = gtk.Label("Presentation is over")
		l_message.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.yellow))
		l_message.show()
		box.pack_start(l_message, False, False, 0)
		
		box_buttons = gtk.HBox(False, 3)
		box_buttons.show()
		box.pack_start(box_buttons, False, False, 0)
		
		btn_close = display.disp.ColoredButton("Close")
		box_buttons.pack_end(btn_close, True, False, 0)
		btn_close.connect("clicked", lambda wid: gtk.main_quit())
		btn_close.show()

class MainWindow(gtk.Window):
	align = None
	login = None
	error = None
	close = None
	presentation = None
	list = None
	
	parser = None
	server = None
	
	def __init__(self):
		gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
		self.connect("destroy", lambda wid : gtk.main_quit())
		self.fullscreen()
		self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(colors.darkgreen))
		self.show()
		
		self.align = gtk.Alignment(0.5, 0.5, 0.0, 0.0)
		self.align.set_padding(0, 0, 0, 0)
		self.align.show()
		self.add(self.align)
		
		self.login = StartUpDisp(self)
		self.login.show()
		self.align.add(self.login)
		
		
	def display_login(self):
		if self.error != None:
			self.error.destroy()
		self.align.add(self.login)
		
		self.align.set(0.5, 0.5, 0.0, 0.0)
		self.align.set_padding(0, 0, 0, 0)
		
	def display_error(self, message):
		self.error = display.disp.ErrorDisp(self, message)
		self.error.show()
		self.align.remove(self.align.get_child())
		self.align.add(self.error)

		self.align.set(0.5, 0.5, 0.0, 0.0)
		self.align.set_padding(0, 0, 0, 0)
		
	def display_slide(self, nr):
		if self.presentation == None:
			self.presentation = SrvDisp(self)
			self.presentation.show()
		self.presentation.display_slide(nr)
		self.align.remove(self.align.get_child())
		self.align.add(self.presentation)

		self.align.set(0.5, 0.5, 1.0, 1.0)
		self.align.set_padding(30, 30, 30, 30)
		
	def display_list(self):
		if self.list != None:
			self.list.destroy()
		stud_list = self.server.get_user_list()

		self.list = ListDisp(self, stud_list)
		self.list.show()
		self.align.remove(self.align.get_child())
		self.align.add(self.list)

		self.align.set(0.5, 0.5, 0.0, 0.0)
		self.align.set_padding(30, 30, 30, 30)
		
	def display_close(self):
		if self.close == None:
			self.close = CloseDisp(self)
			self.close.show()
			
		self.server.stop()

		self.align.remove(self.align.get_child())
		self.align.add(self.close)

		self.align.set(0.5, 0.5, 0.0, 0.0)
		self.align.set_padding(0, 0, 0, 0)

		
def main():
	gtk.main()
	return 0

if __name__ == "__main__":
	MainWindow()
	main()